from flaskr import Utils
import json
import numpy
import time
from flaskr.server.FilterRecord import *
from flaskr.server.SheetsServer import *


class FilterDataServer:
    def __init__(self, session):
        self.session = session
        self.filter_container = {}
        self.filter_record = FilterRecord()

    '''
    获取加载表中的DataFrame对象

    sheet_name 加载表的名字

    return DataFrame对象
    '''
    def getLoadSheet(self, sheet_name):
        return get_dataframe(sheet_name)

    '''
    获取该表的过滤容器中的对象
    sheet_name 过滤对象的加载表的表名
    return DataFrame对象 或者 一个object对象
    '''
    def get_filter_container(self, sheet_name):
        #没有指定哪个表名， 默认为整个过滤容器
        if sheet_name is None:
            return self.filter_container

        df = self.getLoadSheet(sheet_name)

        if df is None:
            remove_sheet(sheet_name)
            return None

        if 'filterContainer' not in self.session.keys():
            self.session['filterContainer'] = {}
            self.filter_container = self.session['filterContainer']

        else:
            self.filter_container = self.session['filterContainer']

        # 如果源数据是一个kpl文件， 那么就读取这个kpl文件
        if has_pkl(sheet_name):
            sheet = get_sheet(sheet_name)
            md5 = get_sheet_md5(sheet_name)
            filter_md5 = md5 + getTime()
            if 'filter_md5' in sheet.keys():# 查看是否存在该文件， 如果不存在就创建此文件
                # if has_pkl_file(filter_md5):
                df = getPkl(sheet['filter_md5'])
                return df.head(200)
            else:
                df = addPkl(df, filter_md5)
                sheet['filter_md5'] = filter_md5
                return df.head(200)

        # 源数据不是一个kpl文件， 并且从未加载到过滤容器当中， 将为它添加到过滤容器当中
        if sheet_name not in self.filter_container.keys():
            if df is None:
                return None

            else:
                self.filter_container[sheet_name] = {}  # 这里面存放的是过滤容器

                self.filter_container[sheet_name] = Utils.dataFrameToJson(df)
                self.session['filterContainer'] = self.filter_container
                return df

        # 返回过滤容器当中的值
        else:
            df = Utils.jsonToDataFrame(self.filter_container[sheet_name])
            return df

    def remove_filter_container(self, sheet_name):
        if has_pkl(sheet_name):
            sheet = get_sheet(sheet_name)
            # md5 = get_sheet_md5(sheet_name)
            filter_md5 = sheet['filter_md5']
            del sheet['filter_md5']

            set_sheet(sheet_name, sheet)

            removePkl(filter_md5)
            return True

        self.filter_container = self.get_filter_container(None)

        if self.filter_container is None or sheet_name not in self.filter_container.keys():
            return False

        del self.filter_container[sheet_name]
        self.session['filterContainer'] = self.filter_container
        return True

    def save_filter(self, sheet_name):
        if has_pkl(sheet_name):
            sheet = get_sheet(sheet_name)
            md5 = get_sheet_md5(sheet_name)
            save_filter_md5 = md5 + getTime() + '_copy'

            if 'copy_md5' in sheet.keys():
                save_filter_md5 = sheet['copy_md5']

            # filter_md5 = md5 + '_filter'
            filter_md5 = sheet['filter_md5']
            df = getPkl(filter_md5)

            if df is None:
                return False

            addPkl(df, save_filter_md5)

            #将md5的值改为过滤后的md5的值， 此时加载表的数据将指向过滤后的md5的值
            sheet['copy_md5'] = save_filter_md5
            sheet['md5'] = save_filter_md5
            sheet['json'] = dataFrameToJson(df)
            sheet['table'] = dataFrameToHtml(df)
            set_sheet(sheet_name, sheet)
            return True

        self.filter_container = self.get_filter_container(None)
        if sheet_name not in self.filter_container.keys():
            return False

        if 'sheets' in self.session.keys():
            sheets = self.session['sheets']

            for i in range(len(sheets)):
                # 将过滤的数据赋值到加载表中
                if sheets[i]['showName'] == sheet_name:
                    json_ = self.filter_container[sheet_name]
                    df = Utils.jsonToDataFrame(json_)
                    table = Utils.dataFrameToHtml(df)

                    sheets[i]['json'] = json_
                    sheets[i]['table'] = table
                    sheets[i]['columns'] = Utils.getColumns(df)

                    self.session['sheets'] = sheets
                    return True
        return False

    def clear_filter_container(self):
        self.filter_container = self.get_filter_container(None)

        self.session['filterContainer'] = {}

    '''
    将数据设置为指定的过滤容器数据
    sheet_name 加载表的表名
    df 指定的数据
    '''
    def set_filter_container(self, sheet_name, df):
        # 判断这个容器是pkl的吗
        if has_pkl(sheet_name):
            sheet = get_sheet(sheet_name)
            md5 = get_sheet_md5(sheet_name)
            filter_md5 = sheet['filter_md5']

            addPkl(df, filter_md5)
            return True

        self.filter_container = self.get_filter_container(None)
        df_json = Utils.dataFrameToJson(df)

        if self.filter_container is not None and sheet_name in self.filter_container.keys():
            self.filter_container[sheet_name] = df_json
            self.session['filterContainer'] = self.filter_container
            return True

        return False

    # 关系运算符解析器
    @staticmethod
    def ro_parse(ro):
        if ro == 'lt':
            return '<'

        elif ro == 'gt':
            return '>'

        elif ro == 'et':
            return '=='

        elif ro == 'ut':
            return '!='

        elif ro == 'get':
            return '>='

        elif ro == 'let':
            return '<='

        else:
            return None

    # 解析客户端传送的条件请求
    @staticmethod
    def parse(data):
        result = ""

        for column in data:
            string = ""
            column_name = column['column']

            for i in range(len(column['value'])):
                ro = FilterDataServer.ro_parse(column['ro'][i])

                if ro is None:
                    return None

                if (column['type'] != 'object'):
                    string += column_name + ro + str(column['value'][i])  # 第i个条件

                else:
                    string += column_name + ro + '"' + str(column['value'][i]) + '"'

                if (i < len(column['logic'])):
                    string += ' ' + column['logic'][i] + ' '  # 条件的逻辑运算符

            result += '(' + string + ')' + ' and '

        # 将多余的and删除
        index = result.rfind(' and')
        result = result[0:index]

        return result

    '''
    将dataFrame对象转换成前端对应的json格式

    data_frame pandas的DataFrame对象

    return DataFrame对象的json
    '''
    def data_frame_to_filter_json(self, data_frame, sheet_name, name):
        data = {}
        columns = Utils.getColumns(data_frame)

        data['json'] = Utils.dataFrameToJson(data_frame)
        data['operationName'] = name
        types = Utils.getTypes(data_frame)

        if name is not None:
            self.filter_record.setRecord(sheet_name, name)
        data['record'] = self.filter_record.getRecord(sheet_name)
        data['types'] = types
        data['data'] = {}
        for i in range(len(types)):
            obj = {}
            values = list(data_frame[columns[i]].values)

            for j in range(len(values)):
                values[j] = str(values[j])

            values = list(numpy.unique(values))

            obj['values'] = values

            data['data'][columns[i]] = obj

        return data

